package com.tangtangtang.gulimall.thirdpaty.TencentUtils;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 高级的Cos的使用方法（带固定线程池）
 */
@Component
public class ThreadCosConfigUtils {
    //腾讯云的密钥id
    @Value("${tencent.secretld}")
    private String secretld;
    //腾讯云的密钥key
    @Value("${tencent.secretkey}")
    private String secretkey;
    //腾讯云服务器位置
    @Value("${tencent.rogin}")
    private String rogin;
    //腾讯云对象存储存储桶名称
    @Value("${tencent.bucket}")
    private String bucket;
    //获取的腾讯云对象存储的固定id
    @Value("${tencent.appid}")
    private String appid;

    @Value("${uploadfile.address}")
    private String multipartfile;

    //文件上传，但是不带签名，但是这个是通过固定的线程池来进行操作的
    public void upload(String filepath)
    {
        //String filepath ="C:/Users/Admin/Pictures/微信图片_20190408223440.jpg";
        //1.初始化创建
        COSCredentials cosCredentials = new BasicCOSCredentials(secretld,secretkey);
        //2.验证区域
        Region region = new Region(rogin);
        ClientConfig clientConfig = new ClientConfig(region);
        //3.初始化客户端
        COSClient cosClient = new COSClient(cosCredentials,clientConfig);

        //4.创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(32);

        //5.通过TransferManager，如果不创建线程池，则使用默认的线程池
        TransferManager transferManager = new TransferManager(cosClient,executorService);

        //6.使用一个uuid作为上传的文件名称
        String suffex = filepath.substring(filepath.lastIndexOf(".")+1);
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        String filekey = uuid+"."+suffex;
        //定义一个时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //7.获得文件路径
        File localfile = new File(filepath);

        //8.验证都是否能推送到cos
        PutObjectRequest put = new PutObjectRequest(bucket,filekey,localfile);

        //9.上传文件
        try{
            System.out.println("上传开始时间："+sdf.format(new Date()));
            Upload upload = transferManager.upload(put);
            //10.同步上传 upload.waitForCompletion()，或者异步上传 upload.waitForUploadResult()
            UploadResult uploadResult = upload.waitForUploadResult();
            System.out.println("上传结束时间："+sdf.format(new Date()));
            System.out.println(uploadResult.getETag());
            System.out.println(uploadResult.getKey());
            //11.获取存储对象的路径
            URL url = cosClient.generatePresignedUrl(bucket,filekey,new Date(new Date().getTime()+5*60*10000));
            System.out.println(url);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //生成带签名的预上传url（这个生成签名是根据每天时间来创建一个bucket来存储新的文件）
    public String UploadUrl(String filepath)
    {
        COSCredentials cred  = new BasicCOSCredentials(secretld,secretkey);
        Region region = new Region(rogin);
        ClientConfig clientConfig = new ClientConfig(region);
        COSClient cosClient = new COSClient(cred,clientConfig);
        //生成预上传的url,有四个参数，第一个是存储对象名称，第二个上传后的文件名称，第三个预上传的时间范围，
        // 第四个，put上去

        //第二个参数
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        String suffux = filepath.substring(filepath.lastIndexOf(".")+1);
        String filekey = uuid+"."+suffux;

        //第三个参数(在半个小时内上传文件)
        Date datetime = new Date(System.currentTimeMillis()+30*60*1000);

        //以时间做为bucket,不一定使用已经创建好的bucket
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String newbucket = String.valueOf(sdf.format(new Date()))+"-"+appid;
        System.out.println("获取的String类型名称为："+newbucket);
        CreateBucketRequest createBucketRequest = new CreateBucketRequest(newbucket);
        createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);//设置权限为公有读，私有写
        try {
            //查询所有的bucket进行比对
            List<Bucket> listBuckets = cosClient.listBuckets();
            for(Bucket bucket:listBuckets){
                System.out.println("显示查询的存储桶数据："+bucket.toString());
                //如果遍历含有日期相等的bucket则直接得出url
                if(bucket.getName().equals(newbucket))
                {
                    //得出上传的预url
                    URL url = cosClient.generatePresignedUrl(newbucket,filekey,datetime,HttpMethodName.PUT);
                    return url.toString();
                }else {
                    //如果没有对象存储文件则先创建一个存储桶文件，
                    Bucket createbucket  = cosClient.createBucket(createBucketRequest);
                    //得出上传的预url
                    URL url = cosClient.generatePresignedUrl(newbucket,filekey,datetime, HttpMethodName.PUT);
                    System.out.println("不存在bucket返回预上传的url为："+url);
                    return url.toString();
                }
            }
        }catch (CosServiceException serverException) {
            serverException.printStackTrace();
        }catch (CosClientException clientException) {
            clientException.printStackTrace();
        }
        return null;
    }

    //使用当天时间来做文件命名，使用创建好的bucket来做文件存储,但是前端在生成签名的时候，上传来的url是一个随机字符串
    public String getfileurluploadtoCos(String filepath)
    {
        COSCredentials cosCredentials = new BasicCOSCredentials(secretld,secretkey);
        Region region = new Region(rogin);
        ClientConfig config = new ClientConfig(region);
        COSClient cosClient = new COSClient(cosCredentials,config);
        //(1)截取名称
        String uploadfilename = filepath.substring(filepath.lastIndexOf("/")+1);

        //(2)上传的时间限制（半个小时）
        Date uploadtime = new Date(System.currentTimeMillis()+30*60*1000);

        //生成签名的URL
        try {
            URL url = cosClient.generatePresignedUrl(bucket,uploadfilename,uploadtime,HttpMethodName.PUT);
            return url.toString();
        }catch (CosServiceException serverException) {
            serverException.printStackTrace();
        }catch (CosClientException clientException) {
            clientException.printStackTrace();
        }
        return null;
    }

    //这个是以为流的方式进行文件上传，带预上传的签名url,以及上传的文件位置,返回一个可以直接访问的路径
    public String uploadurltoCos(String cosurl,String filepath,String filename) throws MalformedURLException {
        //上传成功时，将上传好的url路径进行返回
        COSCredentials cred  = new BasicCOSCredentials(secretld,secretkey);
        Region region = new Region(rogin);
        ClientConfig clientConfig = new ClientConfig(region);
        COSClient cosClient = new COSClient(cred,clientConfig);
        //先将url标转化
        URL url = new URL(cosurl);
        //给一个返回的状态码
        int responseCode = 0;
        try {
            //将文件读取出来
            FileInputStream fileInputStream = new FileInputStream(filepath);
            //打开已经标准化的url
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            //设置上传的写属性为true,上传方式为put
            connection.setDoOutput(true);
            connection.setRequestMethod("PUT");

            //将数据写入数据流（非线程池操作）
            DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
            byte buffer[] = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buffer))!=-1){
                dataOutputStream.write(buffer,0,len);
            }
            dataOutputStream.close();

            responseCode = connection.getResponseCode();
            System.out.println("上传的状态为："+responseCode);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取的这个查看连接只有30分钟时间（这里得修改，如果只有30分钟，后面得图片就不能展示了）
        //这里得时间得改成一个永久有效得时间参数，这里将时间设置为100年为过期时间3600*1000*24*365*100
        //半个小时new Date().getTime()+5*60*10000
        Date data = new Date();
        long datatime= data.getTime()+3600*1000*24*265*100;
        System.out.println("获取100年的时间参数为："+datatime);
        URL getCosUrl = cosClient.generatePresignedUrl(bucket,filename,new Date(datatime));
        /*GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucket,filename,HttpMethodName.GET);
        URL getCosUrl = cosClient.generatePresignedUrl(req);*///如果不设置值参数，这里的最多时间默认为一个小时。
        return getCosUrl.toString();
    }
}
